{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "05f6de1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5524ac38",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import gc\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import re\n",
    "import time\n",
    "from scipy import stats\n",
    "import matplotlib.pyplot as plt\n",
    "import category_encoders as ce\n",
    "import networkx as nx\n",
    "import pickle\n",
    "import lightgbm as lgb\n",
    "import catboost as cat\n",
    "import xgboost as xgb\n",
    "from datetime import timedelta\n",
    "from gensim.models import Word2Vec\n",
    "from io import StringIO\n",
    "from tqdm import tqdm\n",
    "from lightgbm import LGBMClassifier\n",
    "from lightgbm import log_evaluation, early_stopping\n",
    "from sklearn.metrics import roc_curve\n",
    "from scipy.stats import chi2_contingency, pearsonr\n",
    "from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n",
    "from sklearn.feature_extraction import FeatureHasher\n",
    "from sklearn.model_selection import StratifiedKFold, KFold, train_test_split, GridSearchCV\n",
    "from category_encoders import TargetEncoder\n",
    "from sklearn.decomposition import TruncatedSVD\n",
    "from autogluon.tabular import TabularDataset, TabularPredictor, FeatureMetadata\n",
    "from autogluon.features.generators import AsTypeFeatureGenerator, BulkFeatureGenerator, DropUniqueFeatureGenerator, FillNaFeatureGenerator, PipelineFeatureGenerator\n",
    "from autogluon.features.generators import CategoryFeatureGenerator, IdentityFeatureGenerator, AutoMLPipelineFeatureGenerator\n",
    "from autogluon.common.features.types import R_INT, R_FLOAT\n",
    "from autogluon.core.metrics import make_scorer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbbe95e6",
   "metadata": {},
   "source": [
    "# 数据导入"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe6baf61",
   "metadata": {},
   "source": [
    "## 数据导入通用函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6baaf49c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_data_from_directory(directory):\n",
    "    \"\"\"\n",
    "    遍历目录加载所有CSV文件，将其作为独立的DataFrame变量\n",
    "\n",
    "    参数:\n",
    "    - directory: 输入的数据路径\n",
    "    \n",
    "    返回:\n",
    "    - 含有数据集名称的列表\n",
    "    \"\"\"\n",
    "    dataset_names = []\n",
    "    for filename in os.listdir(directory):\n",
    "        if filename.endswith(\".csv\"):\n",
    "            dataset_name = os.path.splitext(filename)[0] + '_data' # 获取文件名作为变量名\n",
    "            file_path = os.path.join(directory, filename)  # 完整的文件路径\n",
    "            globals()[dataset_name] = pd.read_csv(file_path)  # 将文件加载为DataFrame并赋值给全局变量\n",
    "            dataset_names.append(dataset_name)\n",
    "            print(f\"数据集 {dataset_name} 已加载为 DataFrame\")\n",
    "\n",
    "    return dataset_names"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "832fd552",
   "metadata": {},
   "source": [
    "## 导入数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b9aff4e",
   "metadata": {},
   "source": [
    "### 训练集导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e5eeb163",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据集 TRAIN_AGET_PAY_data 已加载为 DataFrame\n",
      "数据集 TRAIN_ASSET_data 已加载为 DataFrame\n",
      "数据集 TRAIN_CCD_TR_DTL_data 已加载为 DataFrame\n",
      "数据集 TRAIN_MB_PAGEVIEW_DTL_data 已加载为 DataFrame\n",
      "数据集 TRAIN_MB_QRYTRNFLW_data 已加载为 DataFrame\n",
      "数据集 TRAIN_MB_TRNFLW_data 已加载为 DataFrame\n",
      "数据集 TRAIN_NATURE_data 已加载为 DataFrame\n",
      "数据集 TRAIN_PROD_HOLD_data 已加载为 DataFrame\n",
      "数据集 TRAIN_TARGET_INFO_data 已加载为 DataFrame\n",
      "数据集 TRAIN_TR_APS_DTL_data 已加载为 DataFrame\n",
      "数据集 TRAIN_TR_IBTF_data 已加载为 DataFrame\n",
      "数据集 TRAIN_TR_TPAY_data 已加载为 DataFrame\n"
     ]
    }
   ],
   "source": [
    "train_load_dt = '../Train_Data'\n",
    "train_data_name = load_data_from_directory(train_load_dt)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3dcd7e43",
   "metadata": {},
   "source": [
    "### A测试集导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "69e63b16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据集 A_AGET_PAY_data 已加载为 DataFrame\n",
      "数据集 A_ASSET_data 已加载为 DataFrame\n",
      "数据集 A_CCD_TR_DTL_data 已加载为 DataFrame\n",
      "数据集 A_MB_PAGEVIEW_DTL_data 已加载为 DataFrame\n",
      "数据集 A_MB_QRYTRNFLW_data 已加载为 DataFrame\n",
      "数据集 A_MB_TRNFLW_data 已加载为 DataFrame\n",
      "数据集 A_NATURE_data 已加载为 DataFrame\n",
      "数据集 A_PROD_HOLD_data 已加载为 DataFrame\n",
      "数据集 A_TARGET_data 已加载为 DataFrame\n",
      "数据集 A_TR_APS_DTL_data 已加载为 DataFrame\n",
      "数据集 A_TR_IBTF_data 已加载为 DataFrame\n",
      "数据集 A_TR_TPAY_data 已加载为 DataFrame\n"
     ]
    }
   ],
   "source": [
    "A_load_dt = '../DATA'\n",
    "A_data_name = load_data_from_directory(A_load_dt)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a885c54",
   "metadata": {},
   "source": [
    "# 特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0f0fe86a",
   "metadata": {},
   "outputs": [],
   "source": [
    "NATURE_data = A_NATURE_data.copy()\n",
    "ASSET_data = A_ASSET_data.copy()\n",
    "PROD_HOLD_data = A_PROD_HOLD_data.copy()\n",
    "TR_TPAY_data = A_TR_TPAY_data.copy()\n",
    "TR_IBTF_data = A_TR_IBTF_data.copy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc16dc60",
   "metadata": {},
   "source": [
    "## 自然属性信息表特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b2026724",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始处理自然属性信息表\n",
      "================================================================================\n",
      "\n",
      "字段类型检查:\n",
      "  性别字段类型: int64, 唯一值: [1, 2]\n",
      "  等级字段类型: int64, 唯一值: [1, 2, 3, 4, 5, 6, 7, 9]\n",
      "  季活标识类型: int64, 唯一值: [0, 1]\n",
      "\n",
      "自然属性信息表特征维度: (5975, 26)\n",
      "生成特征数: 25\n",
      "自然属性信息表处理完成!\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始处理自然属性信息表\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 复制数据避免修改原始数据\n",
    "NATURE_features = NATURE_data.copy()\n",
    "\n",
    "# 1. 检查并直接使用数值型字段\n",
    "# NTRL_CUST_SEX_CD、NTRL_RANK_CD、NTRL_SEAN_ACTV_IND已经是数值型,直接使用\n",
    "print(f\"\\n字段类型检查:\")\n",
    "print(f\"  性别字段类型: {NATURE_features['NTRL_CUST_SEX_CD'].dtype}, 唯一值: {sorted(NATURE_features['NTRL_CUST_SEX_CD'].unique())}\")\n",
    "print(f\"  等级字段类型: {NATURE_features['NTRL_RANK_CD'].dtype}, 唯一值: {sorted(NATURE_features['NTRL_RANK_CD'].unique())}\")\n",
    "print(f\"  季活标识类型: {NATURE_features['NTRL_SEAN_ACTV_IND'].dtype}, 唯一值: {sorted(NATURE_features['NTRL_SEAN_ACTV_IND'].unique())}\")\n",
    "\n",
    "# 直接使用原始数值型字段,不做映射转换\n",
    "NATURE_features['NATURE_SEX_CD'] = NATURE_features['NTRL_CUST_SEX_CD']\n",
    "NATURE_features['NATURE_RANK_CD'] = NATURE_features['NTRL_RANK_CD']\n",
    "NATURE_features['NATURE_SEAN_ACTV_IND'] = NATURE_features['NTRL_SEAN_ACTV_IND']\n",
    "\n",
    "# 2. 年龄特征工程\n",
    "# 年龄分段\n",
    "NATURE_features['NATURE_AGE_GROUP'] = pd.cut(\n",
    "    NATURE_features['NTRL_CUST_AGE'], \n",
    "    bins=[0, 25, 35, 45, 55, 65, 100, 125], \n",
    "    labels=[1, 2, 3, 4, 5, 6, 7]\n",
    ").astype(int)\n",
    "\n",
    "# 年龄平方 (捕捉非线性关系)\n",
    "NATURE_features['NATURE_AGE_SQUARE'] = NATURE_features['NTRL_CUST_AGE'] ** 2\n",
    "\n",
    "# 年龄立方\n",
    "NATURE_features['NATURE_AGE_CUBE'] = NATURE_features['NTRL_CUST_AGE'] ** 3\n",
    "\n",
    "# 3. 交互特征\n",
    "# 年龄与性别交互\n",
    "NATURE_features['NATURE_AGE_SEX_INTERACT'] = NATURE_features['NTRL_CUST_AGE'] * NATURE_features['NATURE_SEX_CD']\n",
    "\n",
    "# 年龄与等级交互\n",
    "NATURE_features['NATURE_AGE_RANK_INTERACT'] = NATURE_features['NTRL_CUST_AGE'] * NATURE_features['NATURE_RANK_CD']\n",
    "\n",
    "# 性别与等级交互\n",
    "NATURE_features['NATURE_SEX_RANK_INTERACT'] = NATURE_features['NATURE_SEX_CD'] * NATURE_features['NATURE_RANK_CD']\n",
    "\n",
    "# 年龄、性别、等级三阶交互\n",
    "NATURE_features['NATURE_AGE_SEX_RANK_INTERACT'] = (\n",
    "    NATURE_features['NTRL_CUST_AGE'] * \n",
    "    NATURE_features['NATURE_SEX_CD'] * \n",
    "    NATURE_features['NATURE_RANK_CD']\n",
    ")\n",
    "\n",
    "# 4. 相对年龄特征\n",
    "# 按性别分组计算相对年龄\n",
    "NATURE_features['NATURE_AGE_BY_SEX_MEAN'] = NATURE_features.groupby('NATURE_SEX_CD')['NTRL_CUST_AGE'].transform('mean')\n",
    "NATURE_features['NATURE_AGE_BY_SEX_STD'] = NATURE_features.groupby('NATURE_SEX_CD')['NTRL_CUST_AGE'].transform('std')\n",
    "NATURE_features['NATURE_AGE_BY_SEX_DIFF'] = NATURE_features['NTRL_CUST_AGE'] - NATURE_features['NATURE_AGE_BY_SEX_MEAN']\n",
    "NATURE_features['NATURE_AGE_BY_SEX_RATIO'] = NATURE_features['NTRL_CUST_AGE'] / (NATURE_features['NATURE_AGE_BY_SEX_MEAN'] + 1e-5)\n",
    "\n",
    "# 按等级分组计算相对年龄\n",
    "NATURE_features['NATURE_AGE_BY_RANK_MEAN'] = NATURE_features.groupby('NATURE_RANK_CD')['NTRL_CUST_AGE'].transform('mean')\n",
    "NATURE_features['NATURE_AGE_BY_RANK_STD'] = NATURE_features.groupby('NATURE_RANK_CD')['NTRL_CUST_AGE'].transform('std')\n",
    "NATURE_features['NATURE_AGE_BY_RANK_DIFF'] = NATURE_features['NTRL_CUST_AGE'] - NATURE_features['NATURE_AGE_BY_RANK_MEAN']\n",
    "NATURE_features['NATURE_AGE_BY_RANK_RATIO'] = NATURE_features['NTRL_CUST_AGE'] / (NATURE_features['NATURE_AGE_BY_RANK_MEAN'] + 1e-5)\n",
    "\n",
    "# 5. 标准化年龄\n",
    "NATURE_features['NATURE_AGE_NORMALIZED'] = (\n",
    "    (NATURE_features['NTRL_CUST_AGE'] - NATURE_features['NTRL_CUST_AGE'].mean()) / \n",
    "    (NATURE_features['NTRL_CUST_AGE'].std() + 1e-5)\n",
    ")\n",
    "\n",
    "# 6. 是否青年/中年/老年\n",
    "NATURE_features['NATURE_IS_YOUNG'] = (NATURE_features['NTRL_CUST_AGE'] <= 30).astype(int)\n",
    "NATURE_features['NATURE_IS_MIDDLE'] = ((NATURE_features['NTRL_CUST_AGE'] > 30) & (NATURE_features['NTRL_CUST_AGE'] <= 50)).astype(int)\n",
    "NATURE_features['NATURE_IS_OLD'] = (NATURE_features['NTRL_CUST_AGE'] > 50).astype(int)\n",
    "\n",
    "# 7. 高等级客户标识\n",
    "NATURE_features['NATURE_IS_HIGH_RANK'] = (NATURE_features['NATURE_RANK_CD'] <= 2).astype(int)\n",
    "NATURE_features['NATURE_IS_LOW_RANK'] = (NATURE_features['NATURE_RANK_CD'] >= 5).astype(int)\n",
    "\n",
    "# 删除不需要的列\n",
    "drop_cols = ['DATA_DAT', 'NTRL_CUST_SEX_CD', 'NTRL_RANK_CD', 'NTRL_SEAN_ACTV_IND']\n",
    "NATURE_features = NATURE_features.drop(columns=[col for col in drop_cols if col in NATURE_features.columns])\n",
    "\n",
    "print(f\"\\n自然属性信息表特征维度: {NATURE_features.shape}\")\n",
    "print(f\"生成特征数: {NATURE_features.shape[1] - 1}\")\n",
    "print(\"自然属性信息表处理完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17b5be98",
   "metadata": {},
   "source": [
    "## 资产信息表特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "4bcc6811",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始处理资产信息表\n",
      "================================================================================\n",
      "资产信息表特征维度: (5624, 139)\n",
      "生成特征数: 138\n",
      "资产信息表处理完成!\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始处理资产信息表\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 复制数据避免修改原始数据\n",
    "ASSET_features = ASSET_data.copy()\n",
    "\n",
    "# 填充缺失值\n",
    "for col in ASSET_features.columns:\n",
    "    if col not in ['CUST_NO', 'DATA_DAT']:\n",
    "        ASSET_features[col] = ASSET_features[col].fillna(0)\n",
    "\n",
    "# ============================================================================\n",
    "# 1. 基础金融资产计算\n",
    "# ============================================================================\n",
    "# 对金额字段进行立方根变换,减少极值影响\n",
    "for col in ASSET_features.columns:\n",
    "    if col not in ['CUST_NO', 'DATA_DAT']:\n",
    "        ASSET_features[col] = ASSET_features[col].apply(lambda x: round(pow(x/3.12, 3), 2) if x > 0 else 0)\n",
    "\n",
    "# 计算当日/月日均/季日均/年日均金融资产 = 存款 + 贷款/2\n",
    "ASSET_features['ASSET_DAY_FA_BAL'] = ASSET_features['AST_DP_BAL'] + ASSET_features['DEBT_LOAN_BAL'] * 0.5\n",
    "ASSET_features['ASSET_MAVER_FA_BAL'] = ASSET_features['AST_MAVER_DP_BAL'] + ASSET_features['DEBT_LOAN_BAL_MAVER'] * 0.5\n",
    "ASSET_features['ASSET_SAVER_FA_BAL'] = ASSET_features['AST_SAVER_DP_BAL'] + ASSET_features['DEBT_LOAN_BAL_SAVER'] * 0.5\n",
    "ASSET_features['ASSET_YAVER_FA_BAL'] = ASSET_features['AST_YAVER_DP_BAL'] + ASSET_features['DEBT_LOAN_BAL_YAVER'] * 0.5\n",
    "\n",
    "# ============================================================================\n",
    "# 2. AUM计算\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_AUM_CALC'] = ASSET_features['ASSET_DAY_FA_BAL'] - ASSET_features['DEBT_LOAN_BAL'] * 0.5\n",
    "ASSET_features['ASSET_MAVER_AUM_CALC'] = ASSET_features['ASSET_MAVER_FA_BAL'] - ASSET_features['DEBT_LOAN_BAL_MAVER'] * 0.5\n",
    "ASSET_features['ASSET_SAVER_AUM_CALC'] = ASSET_features['ASSET_SAVER_FA_BAL'] - ASSET_features['DEBT_LOAN_BAL_SAVER'] * 0.5\n",
    "ASSET_features['ASSET_YAVER_AUM_CALC'] = ASSET_features['ASSET_YAVER_FA_BAL'] - ASSET_features['DEBT_LOAN_BAL_YAVER'] * 0.5\n",
    "\n",
    "# 其他资产 = AUM - 存款\n",
    "ASSET_features['ASSET_DAY_OTR_BAL'] = ASSET_features['ASSET_DAY_AUM_CALC'] - ASSET_features['AST_DP_BAL']\n",
    "ASSET_features['ASSET_MAVER_OTR_BAL'] = ASSET_features['ASSET_MAVER_AUM_CALC'] - ASSET_features['AST_MAVER_DP_BAL']\n",
    "ASSET_features['ASSET_SAVER_OTR_BAL'] = ASSET_features['ASSET_SAVER_AUM_CALC'] - ASSET_features['AST_SAVER_DP_BAL']\n",
    "ASSET_features['ASSET_YAVER_OTR_BAL'] = ASSET_features['ASSET_YAVER_AUM_CALC'] - ASSET_features['AST_YAVER_DP_BAL']\n",
    "\n",
    "# ============================================================================\n",
    "# 3. 定期存款计算\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_TD_BAL'] = ASSET_features['AST_DP_BAL'] - ASSET_features['AST_DPSA_BAL']\n",
    "ASSET_features['ASSET_MAVER_TD_BAL'] = ASSET_features['AST_MAVER_DP_BAL'] - ASSET_features['AST_MAVER_DPSA_BAL']\n",
    "ASSET_features['ASSET_SAVER_TD_BAL'] = ASSET_features['AST_SAVER_DP_BAL'] - ASSET_features['AST_SAVER_DPSA_BAL']\n",
    "ASSET_features['ASSET_YAVER_TD_BAL'] = ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_YAVER_DPSA_BAL']\n",
    "\n",
    "# ============================================================================\n",
    "# 4. AUM与金融资产比率\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_AUM_DIV_FA'] = ASSET_features['AST_DAY_AUM_BAL'] / (ASSET_features['ASSET_DAY_FA_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_AUM_DIV_FA'] = ASSET_features['AST_MAVER_AUM_BAL'] / (ASSET_features['ASSET_MAVER_FA_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_AUM_DIV_FA'] = ASSET_features['AST_SAVER_AUM_BAL'] / (ASSET_features['ASSET_SAVER_FA_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_AUM_DIV_FA'] = ASSET_features['AST_YAVER_AUM_BAL'] / (ASSET_features['ASSET_YAVER_FA_BAL'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 5. 存款与AUM比率\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_DP_DIV_AUM'] = ASSET_features['AST_DP_BAL'] / (ASSET_features['AST_DAY_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_DP_DIV_AUM'] = ASSET_features['AST_MAVER_DP_BAL'] / (ASSET_features['AST_MAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_DP_DIV_AUM'] = ASSET_features['AST_SAVER_DP_BAL'] / (ASSET_features['AST_SAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DP_DIV_AUM'] = ASSET_features['AST_YAVER_DP_BAL'] / (ASSET_features['AST_YAVER_AUM_BAL'] + 1e-5)\n",
    "\n",
    "# 活期存款与AUM比率\n",
    "ASSET_features['ASSET_DAY_DPSA_DIV_AUM'] = ASSET_features['AST_DPSA_BAL'] / (ASSET_features['AST_DAY_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_DPSA_DIV_AUM'] = ASSET_features['AST_MAVER_DPSA_BAL'] / (ASSET_features['AST_MAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_DPSA_DIV_AUM'] = ASSET_features['AST_SAVER_DPSA_BAL'] / (ASSET_features['AST_SAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DPSA_DIV_AUM'] = ASSET_features['AST_YAVER_DPSA_BAL'] / (ASSET_features['AST_YAVER_AUM_BAL'] + 1e-5)\n",
    "\n",
    "# 定期存款与存款比率\n",
    "ASSET_features['ASSET_DAY_TD_DIV_DP'] = ASSET_features['ASSET_DAY_TD_BAL'] / (ASSET_features['AST_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_TD_DIV_DP'] = ASSET_features['ASSET_MAVER_TD_BAL'] / (ASSET_features['AST_MAVER_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_TD_DIV_DP'] = ASSET_features['ASSET_SAVER_TD_BAL'] / (ASSET_features['AST_SAVER_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_TD_DIV_DP'] = ASSET_features['ASSET_YAVER_TD_BAL'] / (ASSET_features['AST_YAVER_DP_BAL'] + 1e-5)\n",
    "\n",
    "# 活期与定期比率\n",
    "ASSET_features['ASSET_DAY_DPSA_DIV_TD'] = ASSET_features['AST_DPSA_BAL'] / (ASSET_features['ASSET_DAY_TD_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_DPSA_DIV_TD'] = ASSET_features['AST_MAVER_DPSA_BAL'] / (ASSET_features['ASSET_MAVER_TD_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_DPSA_DIV_TD'] = ASSET_features['AST_SAVER_DPSA_BAL'] / (ASSET_features['ASSET_SAVER_TD_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DPSA_DIV_TD'] = ASSET_features['AST_YAVER_DPSA_BAL'] / (ASSET_features['ASSET_YAVER_TD_BAL'] + 1e-5)\n",
    "\n",
    "# 活期占总存款比\n",
    "ASSET_features['ASSET_DPSA_DIV_DP'] = ASSET_features['AST_DPSA_BAL'] / (ASSET_features['AST_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DPSA_DIV_DP'] = ASSET_features['AST_YAVER_DPSA_BAL'] / (ASSET_features['AST_YAVER_DP_BAL'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 6. 存贷比特征\n",
    "# ============================================================================\n",
    "# 活期存款与贷款比\n",
    "ASSET_features['ASSET_DAY_DPSA_DIV_LOAN'] = ASSET_features['AST_DPSA_BAL'] / (ASSET_features['DEBT_LOAN_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_DPSA_DIV_LOAN'] = ASSET_features['AST_MAVER_DPSA_BAL'] / (ASSET_features['DEBT_LOAN_BAL_MAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_DPSA_DIV_LOAN'] = ASSET_features['AST_SAVER_DPSA_BAL'] / (ASSET_features['DEBT_LOAN_BAL_SAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DPSA_DIV_LOAN'] = ASSET_features['AST_YAVER_DPSA_BAL'] / (ASSET_features['DEBT_LOAN_BAL_YAVER'] + 1e-5)\n",
    "\n",
    "# 总存款与贷款比\n",
    "ASSET_features['ASSET_DAY_DP_DIV_LOAN'] = ASSET_features['AST_DP_BAL'] / (ASSET_features['DEBT_LOAN_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_DP_DIV_LOAN'] = ASSET_features['AST_MAVER_DP_BAL'] / (ASSET_features['DEBT_LOAN_BAL_MAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_DP_DIV_LOAN'] = ASSET_features['AST_SAVER_DP_BAL'] / (ASSET_features['DEBT_LOAN_BAL_SAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_DP_DIV_LOAN'] = ASSET_features['AST_YAVER_DP_BAL'] / (ASSET_features['DEBT_LOAN_BAL_YAVER'] + 1e-5)\n",
    "\n",
    "# 定期存款与贷款比\n",
    "ASSET_features['ASSET_DAY_TD_DIV_LOAN'] = ASSET_features['ASSET_DAY_TD_BAL'] / (ASSET_features['DEBT_LOAN_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_TD_DIV_LOAN'] = ASSET_features['ASSET_MAVER_TD_BAL'] / (ASSET_features['DEBT_LOAN_BAL_MAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_TD_DIV_LOAN'] = ASSET_features['ASSET_SAVER_TD_BAL'] / (ASSET_features['DEBT_LOAN_BAL_SAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_TD_DIV_LOAN'] = ASSET_features['ASSET_YAVER_TD_BAL'] / (ASSET_features['DEBT_LOAN_BAL_YAVER'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 7. 定期存款与AUM比率\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_TD_DIV_AUM'] = ASSET_features['ASSET_DAY_TD_BAL'] / (ASSET_features['AST_DAY_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_MAVER_TD_DIV_AUM'] = ASSET_features['ASSET_MAVER_TD_BAL'] / (ASSET_features['AST_MAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_SAVER_TD_DIV_AUM'] = ASSET_features['ASSET_SAVER_TD_BAL'] / (ASSET_features['AST_SAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_YAVER_TD_DIV_AUM'] = ASSET_features['ASSET_YAVER_TD_BAL'] / (ASSET_features['AST_YAVER_AUM_BAL'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 8. 日月季年差值特征\n",
    "# ============================================================================\n",
    "period_list = ['DAY', 'MAVER', 'SAVER', 'YAVER']\n",
    "\n",
    "# 8.1 AUM差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_AUM'] = ASSET_features['AST_MAVER_AUM_BAL'] - ASSET_features['AST_DAY_AUM_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_AUM'] = ASSET_features['AST_SAVER_AUM_BAL'] - ASSET_features['AST_DAY_AUM_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_AUM'] = ASSET_features['AST_YAVER_AUM_BAL'] - ASSET_features['AST_DAY_AUM_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_AUM'] = ASSET_features['AST_SAVER_AUM_BAL'] - ASSET_features['AST_MAVER_AUM_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_AUM'] = ASSET_features['AST_YAVER_AUM_BAL'] - ASSET_features['AST_MAVER_AUM_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_AUM'] = ASSET_features['AST_YAVER_AUM_BAL'] - ASSET_features['AST_SAVER_AUM_BAL']\n",
    "\n",
    "# 8.2 其他资产差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_OTR'] = ASSET_features['ASSET_MAVER_OTR_BAL'] - ASSET_features['ASSET_DAY_OTR_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_OTR'] = ASSET_features['ASSET_SAVER_OTR_BAL'] - ASSET_features['ASSET_DAY_OTR_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_OTR'] = ASSET_features['ASSET_YAVER_OTR_BAL'] - ASSET_features['ASSET_DAY_OTR_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_OTR'] = ASSET_features['ASSET_SAVER_OTR_BAL'] - ASSET_features['ASSET_MAVER_OTR_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_OTR'] = ASSET_features['ASSET_YAVER_OTR_BAL'] - ASSET_features['ASSET_MAVER_OTR_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_OTR'] = ASSET_features['ASSET_YAVER_OTR_BAL'] - ASSET_features['ASSET_SAVER_OTR_BAL']\n",
    "\n",
    "# 8.3 贷款差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_MAVER'] - ASSET_features['DEBT_LOAN_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_SAVER'] - ASSET_features['DEBT_LOAN_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_YAVER'] - ASSET_features['DEBT_LOAN_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_SAVER'] - ASSET_features['DEBT_LOAN_BAL_MAVER']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_YAVER'] - ASSET_features['DEBT_LOAN_BAL_MAVER']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_LOAN'] = ASSET_features['DEBT_LOAN_BAL_YAVER'] - ASSET_features['DEBT_LOAN_BAL_SAVER']\n",
    "\n",
    "# 8.4 金融资产差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_FA'] = ASSET_features['ASSET_MAVER_FA_BAL'] - ASSET_features['ASSET_DAY_FA_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_FA'] = ASSET_features['ASSET_SAVER_FA_BAL'] - ASSET_features['ASSET_DAY_FA_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_FA'] = ASSET_features['ASSET_YAVER_FA_BAL'] - ASSET_features['ASSET_DAY_FA_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_FA'] = ASSET_features['ASSET_SAVER_FA_BAL'] - ASSET_features['ASSET_MAVER_FA_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_FA'] = ASSET_features['ASSET_YAVER_FA_BAL'] - ASSET_features['ASSET_MAVER_FA_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_FA'] = ASSET_features['ASSET_YAVER_FA_BAL'] - ASSET_features['ASSET_SAVER_FA_BAL']\n",
    "\n",
    "# 8.5 存款差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_DP'] = ASSET_features['AST_MAVER_DP_BAL'] - ASSET_features['AST_DP_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_DP'] = ASSET_features['AST_SAVER_DP_BAL'] - ASSET_features['AST_DP_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_DP'] = ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_DP_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_DP'] = ASSET_features['AST_SAVER_DP_BAL'] - ASSET_features['AST_MAVER_DP_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_DP'] = ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_MAVER_DP_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_DP'] = ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_SAVER_DP_BAL']\n",
    "\n",
    "# 8.6 活期存款差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_DPSA'] = ASSET_features['AST_MAVER_DPSA_BAL'] - ASSET_features['AST_DPSA_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_DPSA'] = ASSET_features['AST_SAVER_DPSA_BAL'] - ASSET_features['AST_DPSA_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_DPSA'] = ASSET_features['AST_YAVER_DPSA_BAL'] - ASSET_features['AST_DPSA_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_DPSA'] = ASSET_features['AST_SAVER_DPSA_BAL'] - ASSET_features['AST_MAVER_DPSA_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_DPSA'] = ASSET_features['AST_YAVER_DPSA_BAL'] - ASSET_features['AST_MAVER_DPSA_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_DPSA'] = ASSET_features['AST_YAVER_DPSA_BAL'] - ASSET_features['AST_SAVER_DPSA_BAL']\n",
    "\n",
    "# 8.7 定期存款差值\n",
    "ASSET_features['ASSET_DAY_DIFF_MAVER_TD'] = ASSET_features['ASSET_MAVER_TD_BAL'] - ASSET_features['ASSET_DAY_TD_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_SAVER_TD'] = ASSET_features['ASSET_SAVER_TD_BAL'] - ASSET_features['ASSET_DAY_TD_BAL']\n",
    "ASSET_features['ASSET_DAY_DIFF_YAVER_TD'] = ASSET_features['ASSET_YAVER_TD_BAL'] - ASSET_features['ASSET_DAY_TD_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_SAVER_TD'] = ASSET_features['ASSET_SAVER_TD_BAL'] - ASSET_features['ASSET_MAVER_TD_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_YAVER_TD'] = ASSET_features['ASSET_YAVER_TD_BAL'] - ASSET_features['ASSET_MAVER_TD_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_YAVER_TD'] = ASSET_features['ASSET_YAVER_TD_BAL'] - ASSET_features['ASSET_SAVER_TD_BAL']\n",
    "\n",
    "# ============================================================================\n",
    "# 9. 与最大值差值\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_DAY_DIFF_MAX_AUM'] = ASSET_features['AST_AUM_BAL_MAX'] - ASSET_features['AST_DAY_AUM_BAL']\n",
    "ASSET_features['ASSET_MAVER_DIFF_MAX_AUM'] = ASSET_features['AST_AUM_BAL_MAX'] - ASSET_features['AST_MAVER_AUM_BAL']\n",
    "ASSET_features['ASSET_SAVER_DIFF_MAX_AUM'] = ASSET_features['AST_AUM_BAL_MAX'] - ASSET_features['AST_SAVER_AUM_BAL']\n",
    "ASSET_features['ASSET_YAVER_DIFF_MAX_AUM'] = ASSET_features['AST_AUM_BAL_MAX'] - ASSET_features['AST_YAVER_AUM_BAL']\n",
    "\n",
    "# ============================================================================\n",
    "# 10. 资产增长率特征\n",
    "# ============================================================================\n",
    "# AUM增长率\n",
    "ASSET_features['ASSET_AUM_GROWTH_D2M'] = (ASSET_features['AST_MAVER_AUM_BAL'] - ASSET_features['AST_DAY_AUM_BAL']) / (ASSET_features['AST_DAY_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_AUM_GROWTH_M2S'] = (ASSET_features['AST_SAVER_AUM_BAL'] - ASSET_features['AST_MAVER_AUM_BAL']) / (ASSET_features['AST_MAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_AUM_GROWTH_S2Y'] = (ASSET_features['AST_YAVER_AUM_BAL'] - ASSET_features['AST_SAVER_AUM_BAL']) / (ASSET_features['AST_SAVER_AUM_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_AUM_GROWTH_D2Y'] = (ASSET_features['AST_YAVER_AUM_BAL'] - ASSET_features['AST_DAY_AUM_BAL']) / (ASSET_features['AST_DAY_AUM_BAL'] + 1e-5)\n",
    "\n",
    "# 存款增长率\n",
    "ASSET_features['ASSET_DP_GROWTH_D2M'] = (ASSET_features['AST_MAVER_DP_BAL'] - ASSET_features['AST_DP_BAL']) / (ASSET_features['AST_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_DP_GROWTH_M2S'] = (ASSET_features['AST_SAVER_DP_BAL'] - ASSET_features['AST_MAVER_DP_BAL']) / (ASSET_features['AST_MAVER_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_DP_GROWTH_S2Y'] = (ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_SAVER_DP_BAL']) / (ASSET_features['AST_SAVER_DP_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_DP_GROWTH_D2Y'] = (ASSET_features['AST_YAVER_DP_BAL'] - ASSET_features['AST_DP_BAL']) / (ASSET_features['AST_DP_BAL'] + 1e-5)\n",
    "\n",
    "# 贷款增长率\n",
    "ASSET_features['ASSET_LOAN_GROWTH_D2M'] = (ASSET_features['DEBT_LOAN_BAL_MAVER'] - ASSET_features['DEBT_LOAN_BAL']) / (ASSET_features['DEBT_LOAN_BAL'] + 1e-5)\n",
    "ASSET_features['ASSET_LOAN_GROWTH_M2S'] = (ASSET_features['DEBT_LOAN_BAL_SAVER'] - ASSET_features['DEBT_LOAN_BAL_MAVER']) / (ASSET_features['DEBT_LOAN_BAL_MAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_LOAN_GROWTH_S2Y'] = (ASSET_features['DEBT_LOAN_BAL_YAVER'] - ASSET_features['DEBT_LOAN_BAL_SAVER']) / (ASSET_features['DEBT_LOAN_BAL_SAVER'] + 1e-5)\n",
    "ASSET_features['ASSET_LOAN_GROWTH_D2Y'] = (ASSET_features['DEBT_LOAN_BAL_YAVER'] - ASSET_features['DEBT_LOAN_BAL']) / (ASSET_features['DEBT_LOAN_BAL'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 11. 资产波动性特征\n",
    "# ============================================================================\n",
    "# AUM波动系数 (标准差/均值)\n",
    "ASSET_features['ASSET_AUM_CV'] = ASSET_features[['AST_DAY_AUM_BAL', 'AST_MAVER_AUM_BAL', 'AST_SAVER_AUM_BAL', 'AST_YAVER_AUM_BAL']].std(axis=1) / (ASSET_features[['AST_DAY_AUM_BAL', 'AST_MAVER_AUM_BAL', 'AST_SAVER_AUM_BAL', 'AST_YAVER_AUM_BAL']].mean(axis=1) + 1e-5)\n",
    "\n",
    "# 存款波动系数\n",
    "ASSET_features['ASSET_DP_CV'] = ASSET_features[['AST_DP_BAL', 'AST_MAVER_DP_BAL', 'AST_SAVER_DP_BAL', 'AST_YAVER_DP_BAL']].std(axis=1) / (ASSET_features[['AST_DP_BAL', 'AST_MAVER_DP_BAL', 'AST_SAVER_DP_BAL', 'AST_YAVER_DP_BAL']].mean(axis=1) + 1e-5)\n",
    "\n",
    "# 贷款波动系数\n",
    "ASSET_features['ASSET_LOAN_CV'] = ASSET_features[['DEBT_LOAN_BAL', 'DEBT_LOAN_BAL_MAVER', 'DEBT_LOAN_BAL_SAVER', 'DEBT_LOAN_BAL_YAVER']].std(axis=1) / (ASSET_features[['DEBT_LOAN_BAL', 'DEBT_LOAN_BAL_MAVER', 'DEBT_LOAN_BAL_SAVER', 'DEBT_LOAN_BAL_YAVER']].mean(axis=1) + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 12. 资产稳定性标识\n",
    "# ============================================================================\n",
    "ASSET_features['ASSET_IS_HIGH_AUM'] = (ASSET_features['AST_DAY_AUM_BAL'] > ASSET_features['AST_DAY_AUM_BAL'].quantile(0.75)).astype(int)\n",
    "ASSET_features['ASSET_IS_LOW_AUM'] = (ASSET_features['AST_DAY_AUM_BAL'] < ASSET_features['AST_DAY_AUM_BAL'].quantile(0.25)).astype(int)\n",
    "ASSET_features['ASSET_HAS_LOAN'] = (ASSET_features['DEBT_LOAN_BAL'] > 0).astype(int)\n",
    "ASSET_features['ASSET_IS_HIGH_DEPOSIT'] = (ASSET_features['AST_DP_BAL'] > ASSET_features['AST_DP_BAL'].quantile(0.75)).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 13. 资产趋势特征\n",
    "# ============================================================================\n",
    "# 是否资产上升趋势\n",
    "ASSET_features['ASSET_AUM_TREND_UP'] = ((ASSET_features['AST_MAVER_AUM_BAL'] > ASSET_features['AST_DAY_AUM_BAL']) & \n",
    "                                         (ASSET_features['AST_SAVER_AUM_BAL'] > ASSET_features['AST_MAVER_AUM_BAL']) &\n",
    "                                         (ASSET_features['AST_YAVER_AUM_BAL'] > ASSET_features['AST_SAVER_AUM_BAL'])).astype(int)\n",
    "\n",
    "# 是否资产下降趋势\n",
    "ASSET_features['ASSET_AUM_TREND_DOWN'] = ((ASSET_features['AST_MAVER_AUM_BAL'] < ASSET_features['AST_DAY_AUM_BAL']) & \n",
    "                                           (ASSET_features['AST_SAVER_AUM_BAL'] < ASSET_features['AST_MAVER_AUM_BAL']) &\n",
    "                                           (ASSET_features['AST_YAVER_AUM_BAL'] < ASSET_features['AST_SAVER_AUM_BAL'])).astype(int)\n",
    "\n",
    "# 删除不需要的列\n",
    "drop_cols = ['DATA_DAT']\n",
    "ASSET_features = ASSET_features.drop(columns=[col for col in drop_cols if col in ASSET_features.columns])\n",
    "\n",
    "print(f\"资产信息表特征维度: {ASSET_features.shape}\")\n",
    "print(f\"生成特征数: {ASSET_features.shape[1] - 1}\")\n",
    "print(\"资产信息表处理完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c13992b6",
   "metadata": {},
   "source": [
    "## 产品持有信息表特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "0d60809d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始处理产品持有信息表\n",
      "================================================================================\n",
      "产品持有信息表特征维度: (5741, 41)\n",
      "生成特征数: 40\n",
      "产品持有信息表处理完成!\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始处理产品持有信息表\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 复制数据避免修改原始数据\n",
    "PROD_HOLD_features = PROD_HOLD_data.copy()\n",
    "\n",
    "# 填充缺失值\n",
    "for col in PROD_HOLD_features.columns:\n",
    "    if col not in ['CUST_NO', 'DATA_DAT']:\n",
    "        PROD_HOLD_features[col] = PROD_HOLD_features[col].fillna('0')\n",
    "        # 转换为数值\n",
    "        PROD_HOLD_features[col] = PROD_HOLD_features[col].map({'0': 0, '1': 1})\n",
    "\n",
    "# ============================================================================\n",
    "# 1. 产品持有总数统计\n",
    "# ============================================================================\n",
    "# 产品持有总数\n",
    "product_cols = [col for col in PROD_HOLD_features.columns if col.endswith('_IND') and col not in ['CUST_NO', 'DATA_DAT']]\n",
    "PROD_HOLD_features['PROD_TOTAL_COUNT'] = PROD_HOLD_features[product_cols].sum(axis=1)\n",
    "\n",
    "# ============================================================================\n",
    "# 2. 产品类别统计\n",
    "# ============================================================================\n",
    "# 存款类产品\n",
    "PROD_HOLD_features['PROD_DEPOSIT_TYPE'] = PROD_HOLD_features['DP_IND']\n",
    "\n",
    "# 贷款类产品\n",
    "PROD_HOLD_features['PROD_LOAN_TYPE'] = PROD_HOLD_features['IL_IND']\n",
    "\n",
    "# 卡类产品数\n",
    "PROD_HOLD_features['PROD_CARD_COUNT'] = (PROD_HOLD_features['DCARD_IND'] + \n",
    "                                          PROD_HOLD_features['CCARD_IND'])\n",
    "\n",
    "# 理财投资类产品数\n",
    "PROD_HOLD_features['PROD_WEALTH_COUNT'] = (PROD_HOLD_features['FNCG_IND'] + \n",
    "                                            PROD_HOLD_features['FUND_IND'] + \n",
    "                                            PROD_HOLD_features['BOND_IND'] + \n",
    "                                            PROD_HOLD_features['INSUR_IND'] + \n",
    "                                            PROD_HOLD_features['METAL_IND'])\n",
    "\n",
    "# 电子渠道产品数\n",
    "PROD_HOLD_features['PROD_ECHANNEL_COUNT'] = (PROD_HOLD_features['EBNK_IND'] + \n",
    "                                               PROD_HOLD_features['MB_IND'])\n",
    "\n",
    "# 第三方支付产品数\n",
    "PROD_HOLD_features['PROD_THIRDPAY_COUNT'] = (PROD_HOLD_features['TDPT_PAY_ALI_IND'] + \n",
    "                                               PROD_HOLD_features['TDPT_PAY_WCHT_IND'])\n",
    "\n",
    "# ============================================================================\n",
    "# 3. 产品组合特征\n",
    "# ============================================================================\n",
    "# 有贷款且有存款\n",
    "PROD_HOLD_features['PROD_HAS_LOAN_AND_DEPOSIT'] = (PROD_HOLD_features['IL_IND'] & PROD_HOLD_features['DP_IND']).astype(int)\n",
    "\n",
    "# 有信用卡且有借记卡\n",
    "PROD_HOLD_features['PROD_HAS_BOTH_CARDS'] = (PROD_HOLD_features['CCARD_IND'] & PROD_HOLD_features['DCARD_IND']).astype(int)\n",
    "\n",
    "# 有理财且有基金\n",
    "PROD_HOLD_features['PROD_HAS_FNCG_AND_FUND'] = (PROD_HOLD_features['FNCG_IND'] & PROD_HOLD_features['FUND_IND']).astype(int)\n",
    "\n",
    "# 有代发工资\n",
    "PROD_HOLD_features['PROD_HAS_PAY'] = PROD_HOLD_features['PAY_IND']\n",
    "\n",
    "# 使用电子银行\n",
    "PROD_HOLD_features['PROD_USE_EBANK'] = (PROD_HOLD_features['EBNK_IND'] | PROD_HOLD_features['MB_IND']).astype(int)\n",
    "\n",
    "# 使用第三方支付\n",
    "PROD_HOLD_features['PROD_USE_THIRDPAY'] = (PROD_HOLD_features['TDPT_PAY_ALI_IND'] | PROD_HOLD_features['TDPT_PAY_WCHT_IND']).astype(int)\n",
    "\n",
    "# 同时使用支付宝和微信\n",
    "PROD_HOLD_features['PROD_USE_BOTH_PAY'] = (PROD_HOLD_features['TDPT_PAY_ALI_IND'] & PROD_HOLD_features['TDPT_PAY_WCHT_IND']).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 4. 客户价值评分\n",
    "# ============================================================================\n",
    "# 贷款类产品得分高\n",
    "PROD_HOLD_features['PROD_VALUE_SCORE'] = (\n",
    "    PROD_HOLD_features['IL_IND'] * 10 +  # 贷款\n",
    "    PROD_HOLD_features['FNCG_IND'] * 8 +  # 理财\n",
    "    PROD_HOLD_features['FUND_IND'] * 7 +  # 基金\n",
    "    PROD_HOLD_features['INSUR_IND'] * 6 +  # 保险\n",
    "    PROD_HOLD_features['CCARD_IND'] * 5 +  # 信用卡\n",
    "    PROD_HOLD_features['BOND_IND'] * 5 +  # 国债\n",
    "    PROD_HOLD_features['METAL_IND'] * 4 +  # 贵金属\n",
    "    PROD_HOLD_features['DP_IND'] * 3 +  # 存款\n",
    "    PROD_HOLD_features['PAY_IND'] * 3 +  # 代发工资\n",
    "    PROD_HOLD_features['DCARD_IND'] * 2 +  # 借记卡\n",
    "    PROD_HOLD_features['MB_IND'] * 2 +  # 掌银\n",
    "    PROD_HOLD_features['EBNK_IND'] * 1 +  # 网银\n",
    "    PROD_HOLD_features['MS_IND'] * 1  # 消息服务\n",
    ")\n",
    "\n",
    "# ============================================================================\n",
    "# 5. 产品活跃度特征\n",
    "# ============================================================================\n",
    "# 电子渠道活跃度\n",
    "PROD_HOLD_features['PROD_ECHANNEL_ACTIVE'] = (PROD_HOLD_features['MB_IND'] + \n",
    "                                                PROD_HOLD_features['EBNK_IND'] + \n",
    "                                                PROD_HOLD_features['MS_IND'])\n",
    "\n",
    "# 投资活跃度\n",
    "PROD_HOLD_features['PROD_INVEST_ACTIVE'] = (PROD_HOLD_features['FNCG_IND'] + \n",
    "                                              PROD_HOLD_features['FUND_IND'] + \n",
    "                                              PROD_HOLD_features['BOND_IND'] + \n",
    "                                              PROD_HOLD_features['METAL_IND'])\n",
    "\n",
    "# ============================================================================\n",
    "# 6. 产品覆盖率\n",
    "# ============================================================================\n",
    "# 产品覆盖率 (持有产品数/总产品数)\n",
    "total_products = len(product_cols)\n",
    "PROD_HOLD_features['PROD_COVERAGE_RATE'] = PROD_HOLD_features['PROD_TOTAL_COUNT'] / total_products\n",
    "\n",
    "# ============================================================================\n",
    "# 7. 是否高价值客户\n",
    "# ============================================================================\n",
    "PROD_HOLD_features['PROD_IS_HIGH_VALUE'] = (PROD_HOLD_features['PROD_VALUE_SCORE'] > PROD_HOLD_features['PROD_VALUE_SCORE'].quantile(0.75)).astype(int)\n",
    "PROD_HOLD_features['PROD_IS_LOW_VALUE'] = (PROD_HOLD_features['PROD_VALUE_SCORE'] < PROD_HOLD_features['PROD_VALUE_SCORE'].quantile(0.25)).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 8. 产品多样性特征\n",
    "# ============================================================================\n",
    "# 是否多元化投资\n",
    "PROD_HOLD_features['PROD_IS_DIVERSIFIED'] = (PROD_HOLD_features['PROD_INVEST_ACTIVE'] >= 2).astype(int)\n",
    "\n",
    "# 是否全渠道客户\n",
    "PROD_HOLD_features['PROD_IS_OMNICHANNEL'] = (PROD_HOLD_features['PROD_ECHANNEL_ACTIVE'] >= 2).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 9. 特定产品组合\n",
    "# ============================================================================\n",
    "# 高端客户标识: 有理财+基金+保险\n",
    "PROD_HOLD_features['PROD_IS_PREMIUM'] = ((PROD_HOLD_features['FNCG_IND'] == 1) & \n",
    "                                          (PROD_HOLD_features['FUND_IND'] == 1) & \n",
    "                                          (PROD_HOLD_features['INSUR_IND'] == 1)).astype(int)\n",
    "\n",
    "# 基础客户标识: 只有存款和借记卡\n",
    "PROD_HOLD_features['PROD_IS_BASIC'] = ((PROD_HOLD_features['DP_IND'] == 1) & \n",
    "                                        (PROD_HOLD_features['DCARD_IND'] == 1) & \n",
    "                                        (PROD_HOLD_features['PROD_TOTAL_COUNT'] <= 3)).astype(int)\n",
    "\n",
    "# 信贷客户标识\n",
    "PROD_HOLD_features['PROD_IS_CREDIT_CUSTOMER'] = ((PROD_HOLD_features['IL_IND'] == 1) | \n",
    "                                                  (PROD_HOLD_features['CCARD_IND'] == 1)).astype(int)\n",
    "\n",
    "# 删除不需要的列\n",
    "drop_cols = ['DATA_DAT']\n",
    "PROD_HOLD_features = PROD_HOLD_features.drop(columns=[col for col in drop_cols if col in PROD_HOLD_features.columns])\n",
    "\n",
    "print(f\"产品持有信息表特征维度: {PROD_HOLD_features.shape}\")\n",
    "print(f\"生成特征数: {PROD_HOLD_features.shape[1] - 1}\")\n",
    "print(\"产品持有信息表处理完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb6d9414",
   "metadata": {},
   "source": [
    "## 第三方支付交易表特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "5405ef49",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始处理第三方支付交易表\n",
      "================================================================================\n",
      "第三方支付交易表特征维度: (3595, 65)\n",
      "生成特征数: 64\n",
      "第三方支付交易表处理完成!\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始处理第三方支付交易表\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 复制数据避免修改原始数据\n",
    "TR_TPAY_features = TR_TPAY_data.copy()\n",
    "\n",
    "# 填充缺失值\n",
    "for col in TR_TPAY_features.columns:\n",
    "    if col not in ['CUST_NO', 'DATA_DAT']:\n",
    "        TR_TPAY_features[col] = TR_TPAY_features[col].fillna(0)\n",
    "\n",
    "# ============================================================================\n",
    "# 1. 其他支付平台交易\n",
    "# ============================================================================\n",
    "# 其他支付金额 = 总金额 - 支付宝 - 微信\n",
    "TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT'] = (TR_TPAY_features['TPAY_MOTH_TR_AMT'] - \n",
    "                                               TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] - \n",
    "                                               TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'])\n",
    "TR_TPAY_features['TPAY_OTHER_SEAN_TR_AMT'] = (TR_TPAY_features['TPAY_SEAN_TR_AMT'] - \n",
    "                                               TR_TPAY_features['TPAY_WX_SEAN_TR_AMT'] - \n",
    "                                               TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT'])\n",
    "\n",
    "# 其他支付笔数 = 总笔数 - 支付宝 - 微信\n",
    "TR_TPAY_features['TPAY_OTHER_MOTH_TR_CNT'] = (TR_TPAY_features['TPAY_MOTH_TR_CNT'] - \n",
    "                                               TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] - \n",
    "                                               TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'])\n",
    "TR_TPAY_features['TPAY_OTHER_SEAN_TR_CNT'] = (TR_TPAY_features['TPAY_SEAN_TR_CNT'] - \n",
    "                                               TR_TPAY_features['TPAY_WX_SEAN_TR_CNT'] - \n",
    "                                               TR_TPAY_features['TPAY_ALI_SEAN_TR_CNT'])\n",
    "\n",
    "# ============================================================================\n",
    "# 2. 净交易/总交易比率\n",
    "# ============================================================================\n",
    "TR_TPAY_features['TPAY_MOTH_NET_DIV_ALL'] = TR_TPAY_features['TPAY_MOTH_NET_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_SEAN_NET_DIV_ALL'] = TR_TPAY_features['TPAY_SEAN_NET_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_AMT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 3. 笔均交易金额\n",
    "# ============================================================================\n",
    "# 总体笔均\n",
    "TR_TPAY_features['TPAY_MOTH_TR_AMT_EACH'] = TR_TPAY_features['TPAY_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_SEAN_TR_AMT_EACH'] = TR_TPAY_features['TPAY_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 微信笔均\n",
    "TR_TPAY_features['TPAY_WX_MOTH_TR_AMT_EACH'] = TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_SEAN_TR_AMT_EACH'] = TR_TPAY_features['TPAY_WX_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_WX_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 支付宝笔均\n",
    "TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT_EACH'] = TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT_EACH'] = TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_ALI_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 其他支付笔均\n",
    "TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT_EACH'] = TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_OTHER_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_OTHER_SEAN_TR_AMT_EACH'] = TR_TPAY_features['TPAY_OTHER_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_OTHER_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 4. 月季交易对比\n",
    "# ============================================================================\n",
    "# 季月金额比\n",
    "TR_TPAY_features['TPAY_SEAN_DIV_MOTH_AMT'] = TR_TPAY_features['TPAY_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_SEAN_DIV_MOTH_AMT'] = TR_TPAY_features['TPAY_WX_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_SEAN_DIV_MOTH_AMT'] = TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'] + 1e-5)\n",
    "\n",
    "# 季月笔数比\n",
    "TR_TPAY_features['TPAY_SEAN_DIV_MOTH_CNT'] = TR_TPAY_features['TPAY_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_SEAN_DIV_MOTH_CNT'] = TR_TPAY_features['TPAY_WX_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_SEAN_DIV_MOTH_CNT'] = TR_TPAY_features['TPAY_ALI_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 月季差值\n",
    "TR_TPAY_features['TPAY_SEAN_MINUS_MOTH_AMT'] = TR_TPAY_features['TPAY_SEAN_TR_AMT'] - TR_TPAY_features['TPAY_MOTH_TR_AMT']\n",
    "TR_TPAY_features['TPAY_SEAN_MINUS_MOTH_CNT'] = TR_TPAY_features['TPAY_SEAN_TR_CNT'] - TR_TPAY_features['TPAY_MOTH_TR_CNT']\n",
    "\n",
    "# ============================================================================\n",
    "# 5. 支付渠道占比\n",
    "# ============================================================================\n",
    "# 微信占比\n",
    "TR_TPAY_features['TPAY_WX_MOTH_AMT_RATIO'] = TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_SEAN_AMT_RATIO'] = TR_TPAY_features['TPAY_WX_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_MOTH_CNT_RATIO'] = TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] / (TR_TPAY_features['TPAY_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_SEAN_CNT_RATIO'] = TR_TPAY_features['TPAY_WX_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 支付宝占比\n",
    "TR_TPAY_features['TPAY_ALI_MOTH_AMT_RATIO'] = TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_SEAN_AMT_RATIO'] = TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_MOTH_CNT_RATIO'] = TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] / (TR_TPAY_features['TPAY_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_ALI_SEAN_CNT_RATIO'] = TR_TPAY_features['TPAY_ALI_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 其他支付占比\n",
    "TR_TPAY_features['TPAY_OTHER_MOTH_AMT_RATIO'] = TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_OTHER_SEAN_AMT_RATIO'] = TR_TPAY_features['TPAY_OTHER_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_OTHER_MOTH_CNT_RATIO'] = TR_TPAY_features['TPAY_OTHER_MOTH_TR_CNT'] / (TR_TPAY_features['TPAY_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_OTHER_SEAN_CNT_RATIO'] = TR_TPAY_features['TPAY_OTHER_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 6. 支付渠道偏好\n",
    "# ============================================================================\n",
    "# 微信vs支付宝 (微信/支付宝)\n",
    "TR_TPAY_features['TPAY_WX_DIV_ALI_MOTH_AMT'] = TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] / (TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_DIV_ALI_SEAN_AMT'] = TR_TPAY_features['TPAY_WX_SEAN_TR_AMT'] / (TR_TPAY_features['TPAY_ALI_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_DIV_ALI_MOTH_CNT'] = TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] / (TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_WX_DIV_ALI_SEAN_CNT'] = TR_TPAY_features['TPAY_WX_SEAN_TR_CNT'] / (TR_TPAY_features['TPAY_ALI_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 主力支付渠道 (1=微信, 2=支付宝, 3=其他, 0=未使用)\n",
    "TR_TPAY_features['TPAY_MOTH_MAIN_CHANNEL'] = 0\n",
    "TR_TPAY_features.loc[TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'] > TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'], 'TPAY_MOTH_MAIN_CHANNEL'] = 1\n",
    "TR_TPAY_features.loc[TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT'] > TR_TPAY_features['TPAY_WX_MOTH_TR_AMT'], 'TPAY_MOTH_MAIN_CHANNEL'] = 2\n",
    "TR_TPAY_features.loc[(TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT'] > TR_TPAY_features['TPAY_WX_MOTH_TR_AMT']) & \n",
    "                     (TR_TPAY_features['TPAY_OTHER_MOTH_TR_AMT'] > TR_TPAY_features['TPAY_ALI_MOTH_TR_AMT']), 'TPAY_MOTH_MAIN_CHANNEL'] = 3\n",
    "\n",
    "# ============================================================================\n",
    "# 7. 交易活跃度标识\n",
    "# ============================================================================\n",
    "TR_TPAY_features['TPAY_IS_ACTIVE_MOTH'] = (TR_TPAY_features['TPAY_MOTH_TR_CNT'] > 0).astype(int)\n",
    "TR_TPAY_features['TPAY_IS_ACTIVE_SEAN'] = (TR_TPAY_features['TPAY_SEAN_TR_CNT'] > 0).astype(int)\n",
    "TR_TPAY_features['TPAY_IS_HIGH_FREQ'] = (TR_TPAY_features['TPAY_MOTH_TR_CNT'] > TR_TPAY_features['TPAY_MOTH_TR_CNT'].quantile(0.75)).astype(int)\n",
    "TR_TPAY_features['TPAY_IS_HIGH_AMOUNT'] = (TR_TPAY_features['TPAY_MOTH_TR_AMT'] > TR_TPAY_features['TPAY_MOTH_TR_AMT'].quantile(0.75)).astype(int)\n",
    "\n",
    "# 是否使用微信/支付宝\n",
    "TR_TPAY_features['TPAY_USE_WX'] = (TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] > 0).astype(int)\n",
    "TR_TPAY_features['TPAY_USE_ALI'] = (TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] > 0).astype(int)\n",
    "TR_TPAY_features['TPAY_USE_BOTH'] = ((TR_TPAY_features['TPAY_WX_MOTH_TR_CNT'] > 0) & (TR_TPAY_features['TPAY_ALI_MOTH_TR_CNT'] > 0)).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 8. 净交易特征\n",
    "# ============================================================================\n",
    "# 净交易率 (净交易/总交易)\n",
    "TR_TPAY_features['TPAY_MOTH_NET_RATE'] = TR_TPAY_features['TPAY_MOTH_NET_TR_AMT'] / (TR_TPAY_features['TPAY_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_TPAY_features['TPAY_SEAN_NET_RATE'] = TR_TPAY_features['TPAY_SEAN_NET_TR_AMT'] / (TR_TPAY_features['TPAY_SEAN_TR_AMT'] + 1e-5)\n",
    "\n",
    "# 是否净流入\n",
    "TR_TPAY_features['TPAY_MOTH_IS_NET_IN'] = (TR_TPAY_features['TPAY_MOTH_NET_TR_AMT'] > 0).astype(int)\n",
    "TR_TPAY_features['TPAY_SEAN_IS_NET_IN'] = (TR_TPAY_features['TPAY_SEAN_NET_TR_AMT'] > 0).astype(int)\n",
    "\n",
    "# 删除不需要的列\n",
    "drop_cols = ['DATA_DAT']\n",
    "TR_TPAY_features = TR_TPAY_features.drop(columns=[col for col in drop_cols if col in TR_TPAY_features.columns])\n",
    "\n",
    "print(f\"第三方支付交易表特征维度: {TR_TPAY_features.shape}\")\n",
    "print(f\"生成特征数: {TR_TPAY_features.shape[1] - 1}\")\n",
    "print(\"第三方支付交易表处理完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54020cfb",
   "metadata": {},
   "source": [
    "## 跨行转账信息表特征工程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "eb559bf0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始处理跨行转账信息表\n",
      "================================================================================\n",
      "跨行转账信息表特征维度: (2981, 86)\n",
      "生成特征数: 85\n",
      "跨行转账信息表处理完成!\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始处理跨行转账信息表\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 复制数据避免修改原始数据\n",
    "TR_IBTF_features = TR_IBTF_data.copy()\n",
    "\n",
    "# 填充缺失值\n",
    "for col in TR_IBTF_features.columns:\n",
    "    if col not in ['CUST_NO', 'DATA_DAT']:\n",
    "        TR_IBTF_features[col] = TR_IBTF_features[col].fillna(0)\n",
    "\n",
    "# ============================================================================\n",
    "# 1. 转出笔数计算\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_CNT_OUT'] = TR_IBTF_features['IBTF_TR_CNT'] - TR_IBTF_features['IBTF_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_MOTH_TR_CNT_OUT'] = TR_IBTF_features['IBTF_MOTH_TR_CNT'] - TR_IBTF_features['IBTF_MOTH_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_SEAN_TR_CNT_OUT'] = TR_IBTF_features['IBTF_SEAN_TR_CNT'] - TR_IBTF_features['IBTF_SEAN_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_YEAR_TR_CNT_OUT'] = TR_IBTF_features['IBTF_YEAR_TR_CNT'] - TR_IBTF_features['IBTF_YEAR_TR_CNT_IN']\n",
    "\n",
    "# ============================================================================\n",
    "# 2. 转出转入笔数差 (净笔数)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_CNT_NET'] = TR_IBTF_features['IBTF_TR_CNT_OUT'] - TR_IBTF_features['IBTF_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_MOTH_TR_CNT_NET'] = TR_IBTF_features['IBTF_MOTH_TR_CNT_OUT'] - TR_IBTF_features['IBTF_MOTH_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_SEAN_TR_CNT_NET'] = TR_IBTF_features['IBTF_SEAN_TR_CNT_OUT'] - TR_IBTF_features['IBTF_SEAN_TR_CNT_IN']\n",
    "TR_IBTF_features['IBTF_YEAR_TR_CNT_NET'] = TR_IBTF_features['IBTF_YEAR_TR_CNT_OUT'] - TR_IBTF_features['IBTF_YEAR_TR_CNT_IN']\n",
    "\n",
    "# ============================================================================\n",
    "# 3. 转出金额计算\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_OUT'] = TR_IBTF_features['IBTF_TR_AMT'] - TR_IBTF_features['IBTF_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT'] = TR_IBTF_features['IBTF_MOTH_TR_AMT'] - TR_IBTF_features['IBTF_MOTH_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT'] = TR_IBTF_features['IBTF_SEAN_TR_AMT'] - TR_IBTF_features['IBTF_SEAN_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT'] = TR_IBTF_features['IBTF_YEAR_TR_AMT'] - TR_IBTF_features['IBTF_YEAR_TR_AMT_IN']\n",
    "\n",
    "# ============================================================================\n",
    "# 4. 转出转入金额差 (净金额)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_NET'] = TR_IBTF_features['IBTF_TR_AMT_OUT'] - TR_IBTF_features['IBTF_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_NET'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT'] - TR_IBTF_features['IBTF_MOTH_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_NET'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT'] - TR_IBTF_features['IBTF_SEAN_TR_AMT_IN']\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_NET'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT'] - TR_IBTF_features['IBTF_YEAR_TR_AMT_IN']\n",
    "\n",
    "# ============================================================================\n",
    "# 5. 净交易/总交易比率 (金额)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_TR_AMT_NET'] / (TR_IBTF_features['IBTF_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_NET'] / (TR_IBTF_features['IBTF_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_NET'] / (TR_IBTF_features['IBTF_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_NET'] / (TR_IBTF_features['IBTF_YEAR_TR_AMT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 6. 净交易/总交易比率 (笔数)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_CNT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_TR_CNT_NET'] / (TR_IBTF_features['IBTF_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_CNT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_MOTH_TR_CNT_NET'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_CNT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_SEAN_TR_CNT_NET'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_CNT_NET_DIV_ALL'] = TR_IBTF_features['IBTF_YEAR_TR_CNT_NET'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 7. 笔均转入金额\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_IN_EACH'] = TR_IBTF_features['IBTF_TR_AMT_IN'] / (TR_IBTF_features['IBTF_TR_CNT_IN'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_IN_EACH'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_IN'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT_IN'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_IN_EACH'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_IN'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT_IN'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_IN_EACH'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_IN'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT_IN'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 8. 笔均转出金额\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_OUT_EACH'] = TR_IBTF_features['IBTF_TR_AMT_OUT'] / (TR_IBTF_features['IBTF_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT_EACH'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT_EACH'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT_EACH'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT_OUT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 9. 笔均总交易金额\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_EACH'] = TR_IBTF_features['IBTF_TR_AMT'] / (TR_IBTF_features['IBTF_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_EACH'] = TR_IBTF_features['IBTF_MOTH_TR_AMT'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_EACH'] = TR_IBTF_features['IBTF_SEAN_TR_AMT'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_EACH'] = TR_IBTF_features['IBTF_YEAR_TR_AMT'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 10. 流入流出比率 (金额)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_TR_AMT_IN'] / (TR_IBTF_features['IBTF_TR_AMT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_IN'] / (TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_IN'] / (TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_IN'] / (TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 11. 流入流出比率 (笔数)\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_CNT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_TR_CNT_IN'] / (TR_IBTF_features['IBTF_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_CNT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_MOTH_TR_CNT_IN'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_CNT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_SEAN_TR_CNT_IN'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT_OUT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_CNT_IN_DIV_OUT'] = TR_IBTF_features['IBTF_YEAR_TR_CNT_IN'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT_OUT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 12. 流入占比\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_TR_AMT_IN_RATIO'] = TR_IBTF_features['IBTF_TR_AMT_IN'] / (TR_IBTF_features['IBTF_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_AMT_IN_RATIO'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_IN'] / (TR_IBTF_features['IBTF_MOTH_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_AMT_IN_RATIO'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_IN'] / (TR_IBTF_features['IBTF_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_AMT_IN_RATIO'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_IN'] / (TR_IBTF_features['IBTF_YEAR_TR_AMT'] + 1e-5)\n",
    "\n",
    "TR_IBTF_features['IBTF_TR_CNT_IN_RATIO'] = TR_IBTF_features['IBTF_TR_CNT_IN'] / (TR_IBTF_features['IBTF_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_TR_CNT_IN_RATIO'] = TR_IBTF_features['IBTF_MOTH_TR_CNT_IN'] / (TR_IBTF_features['IBTF_MOTH_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_TR_CNT_IN_RATIO'] = TR_IBTF_features['IBTF_SEAN_TR_CNT_IN'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_YEAR_TR_CNT_IN_RATIO'] = TR_IBTF_features['IBTF_YEAR_TR_CNT_IN'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 13. 时间周期对比\n",
    "# ============================================================================\n",
    "# 月/年比率\n",
    "TR_IBTF_features['IBTF_MOTH_DIV_YEAR_AMT'] = TR_IBTF_features['IBTF_MOTH_TR_AMT'] / (TR_IBTF_features['IBTF_YEAR_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_DIV_YEAR_CNT'] = TR_IBTF_features['IBTF_MOTH_TR_CNT'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 季/年比率\n",
    "TR_IBTF_features['IBTF_SEAN_DIV_YEAR_AMT'] = TR_IBTF_features['IBTF_SEAN_TR_AMT'] / (TR_IBTF_features['IBTF_YEAR_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_SEAN_DIV_YEAR_CNT'] = TR_IBTF_features['IBTF_SEAN_TR_CNT'] / (TR_IBTF_features['IBTF_YEAR_TR_CNT'] + 1e-5)\n",
    "\n",
    "# 月/季比率\n",
    "TR_IBTF_features['IBTF_MOTH_DIV_SEAN_AMT'] = TR_IBTF_features['IBTF_MOTH_TR_AMT'] / (TR_IBTF_features['IBTF_SEAN_TR_AMT'] + 1e-5)\n",
    "TR_IBTF_features['IBTF_MOTH_DIV_SEAN_CNT'] = TR_IBTF_features['IBTF_MOTH_TR_CNT'] / (TR_IBTF_features['IBTF_SEAN_TR_CNT'] + 1e-5)\n",
    "\n",
    "# ============================================================================\n",
    "# 14. 交易活跃度标识\n",
    "# ============================================================================\n",
    "TR_IBTF_features['IBTF_IS_ACTIVE'] = (TR_IBTF_features['IBTF_TR_CNT'] > 0).astype(int)\n",
    "TR_IBTF_features['IBTF_IS_HIGH_FREQ'] = (TR_IBTF_features['IBTF_MOTH_TR_CNT'] > TR_IBTF_features['IBTF_MOTH_TR_CNT'].quantile(0.75)).astype(int)\n",
    "TR_IBTF_features['IBTF_IS_HIGH_AMOUNT'] = (TR_IBTF_features['IBTF_MOTH_TR_AMT'] > TR_IBTF_features['IBTF_MOTH_TR_AMT'].quantile(0.75)).astype(int)\n",
    "\n",
    "# 是否净流入\n",
    "TR_IBTF_features['IBTF_IS_NET_IN'] = (TR_IBTF_features['IBTF_TR_AMT_NET'] > 0).astype(int)\n",
    "TR_IBTF_features['IBTF_MOTH_IS_NET_IN'] = (TR_IBTF_features['IBTF_MOTH_TR_AMT_NET'] > 0).astype(int)\n",
    "TR_IBTF_features['IBTF_SEAN_IS_NET_IN'] = (TR_IBTF_features['IBTF_SEAN_TR_AMT_NET'] > 0).astype(int)\n",
    "TR_IBTF_features['IBTF_YEAR_IS_NET_IN'] = (TR_IBTF_features['IBTF_YEAR_TR_AMT_NET'] > 0).astype(int)\n",
    "\n",
    "# ============================================================================\n",
    "# 15. 笔均金额差异\n",
    "# ============================================================================\n",
    "# 转入转出笔均差\n",
    "TR_IBTF_features['IBTF_AMT_IN_OUT_EACH_DIFF'] = TR_IBTF_features['IBTF_TR_AMT_IN_EACH'] - TR_IBTF_features['IBTF_TR_AMT_OUT_EACH']\n",
    "TR_IBTF_features['IBTF_MOTH_AMT_IN_OUT_EACH_DIFF'] = TR_IBTF_features['IBTF_MOTH_TR_AMT_IN_EACH'] - TR_IBTF_features['IBTF_MOTH_TR_AMT_OUT_EACH']\n",
    "TR_IBTF_features['IBTF_SEAN_AMT_IN_OUT_EACH_DIFF'] = TR_IBTF_features['IBTF_SEAN_TR_AMT_IN_EACH'] - TR_IBTF_features['IBTF_SEAN_TR_AMT_OUT_EACH']\n",
    "TR_IBTF_features['IBTF_YEAR_AMT_IN_OUT_EACH_DIFF'] = TR_IBTF_features['IBTF_YEAR_TR_AMT_IN_EACH'] - TR_IBTF_features['IBTF_YEAR_TR_AMT_OUT_EACH']\n",
    "\n",
    "# 删除不需要的列\n",
    "drop_cols = ['DATA_DAT']\n",
    "TR_IBTF_features = TR_IBTF_features.drop(columns=[col for col in drop_cols if col in TR_IBTF_features.columns])\n",
    "\n",
    "print(f\"跨行转账信息表特征维度: {TR_IBTF_features.shape}\")\n",
    "print(f\"生成特征数: {TR_IBTF_features.shape[1] - 1}\")\n",
    "print(\"跨行转账信息表处理完成!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96208ffa",
   "metadata": {},
   "source": [
    "## 特征保存"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8448988",
   "metadata": {},
   "source": [
    "### 训练集保存"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "65b9e3a5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始保存特征\n",
      "================================================================================\n",
      "\n",
      "保存自然属性信息表特征...\n",
      "保存完成: TRAIN_NATURE_features.pkl, 特征数: 25, 样本数: 51397\n",
      "\n",
      "保存资产信息表特征...\n",
      "保存完成: TRAIN_ASSET_features.pkl, 特征数: 138, 样本数: 48417\n",
      "\n",
      "保存产品持有信息表特征...\n",
      "保存完成: TRAIN_PROD_HOLD_features.pkl, 特征数: 40, 样本数: 49448\n",
      "\n",
      "保存第三方支付交易表特征...\n",
      "保存完成: TRAIN_TR_TPAY_features.pkl, 特征数: 64, 样本数: 30926\n",
      "\n",
      "保存跨行转账信息表特征...\n",
      "保存完成: TRAIN_TR_IBTF_features.pkl, 特征数: 85, 样本数: 26375\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始保存特征\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 检查feature目录\n",
    "feature_dir = 'feature/Train'\n",
    "if not os.path.exists(feature_dir):\n",
    "    os.makedirs(feature_dir)\n",
    "\n",
    "# 保存各表特征\n",
    "print(\"\\n保存自然属性信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'TRAIN_NATURE_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(NATURE_features, f)\n",
    "print(f\"保存完成: TRAIN_NATURE_features.pkl, 特征数: {NATURE_features.shape[1]-1}, 样本数: {NATURE_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存资产信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'TRAIN_ASSET_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(ASSET_features, f)\n",
    "print(f\"保存完成: TRAIN_ASSET_features.pkl, 特征数: {ASSET_features.shape[1]-1}, 样本数: {ASSET_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存产品持有信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'TRAIN_PROD_HOLD_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(PROD_HOLD_features, f)\n",
    "print(f\"保存完成: TRAIN_PROD_HOLD_features.pkl, 特征数: {PROD_HOLD_features.shape[1]-1}, 样本数: {PROD_HOLD_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存第三方支付交易表特征...\")\n",
    "with open(os.path.join(feature_dir, 'TRAIN_TR_TPAY_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(TR_TPAY_features, f)\n",
    "print(f\"保存完成: TRAIN_TR_TPAY_features.pkl, 特征数: {TR_TPAY_features.shape[1]-1}, 样本数: {TR_TPAY_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存跨行转账信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'TRAIN_TR_IBTF_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(TR_IBTF_features, f)\n",
    "print(f\"保存完成: TRAIN_TR_IBTF_features.pkl, 特征数: {TR_IBTF_features.shape[1]-1}, 样本数: {TR_IBTF_features.shape[0]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6745a6fa",
   "metadata": {},
   "source": [
    "### A测试集保存"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ca67b745",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================================================\n",
      "开始保存特征\n",
      "================================================================================\n",
      "\n",
      "保存自然属性信息表特征...\n",
      "保存完成: A_NATURE_features.pkl, 特征数: 25, 样本数: 5975\n",
      "\n",
      "保存资产信息表特征...\n",
      "保存完成: A_ASSET_features.pkl, 特征数: 138, 样本数: 5624\n",
      "\n",
      "保存产品持有信息表特征...\n",
      "保存完成: A_PROD_HOLD_features.pkl, 特征数: 40, 样本数: 5741\n",
      "\n",
      "保存第三方支付交易表特征...\n",
      "保存完成: A_TR_TPAY_features.pkl, 特征数: 64, 样本数: 3595\n",
      "\n",
      "保存跨行转账信息表特征...\n",
      "保存完成: A_TR_IBTF_features.pkl, 特征数: 85, 样本数: 2981\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*80)\n",
    "print(\"开始保存特征\")\n",
    "print(\"=\"*80)\n",
    "\n",
    "# 检查feature目录\n",
    "feature_dir = 'feature/A'\n",
    "if not os.path.exists(feature_dir):\n",
    "    os.makedirs(feature_dir)\n",
    "\n",
    "# 保存各表特征\n",
    "print(\"\\n保存自然属性信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'A_NATURE_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(NATURE_features, f)\n",
    "print(f\"保存完成: A_NATURE_features.pkl, 特征数: {NATURE_features.shape[1]-1}, 样本数: {NATURE_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存资产信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'A_ASSET_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(ASSET_features, f)\n",
    "print(f\"保存完成: A_ASSET_features.pkl, 特征数: {ASSET_features.shape[1]-1}, 样本数: {ASSET_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存产品持有信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'A_PROD_HOLD_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(PROD_HOLD_features, f)\n",
    "print(f\"保存完成: A_PROD_HOLD_features.pkl, 特征数: {PROD_HOLD_features.shape[1]-1}, 样本数: {PROD_HOLD_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存第三方支付交易表特征...\")\n",
    "with open(os.path.join(feature_dir, 'A_TR_TPAY_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(TR_TPAY_features, f)\n",
    "print(f\"保存完成: A_TR_TPAY_features.pkl, 特征数: {TR_TPAY_features.shape[1]-1}, 样本数: {TR_TPAY_features.shape[0]}\")\n",
    "\n",
    "print(\"\\n保存跨行转账信息表特征...\")\n",
    "with open(os.path.join(feature_dir, 'A_TR_IBTF_features.pkl'), 'wb') as f:\n",
    "    pickle.dump(TR_IBTF_features, f)\n",
    "print(f\"保存完成: A_TR_IBTF_features.pkl, 特征数: {TR_IBTF_features.shape[1]-1}, 样本数: {TR_IBTF_features.shape[0]}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1920ec74",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "starcup",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
